package com.pj.ca.service.impl;

import com.pj.ca.service.AsymmetricalCipher;
import com.pj.ca.service.AsymmetricalSignature;
import com.pj.ca.util.AsymmetricalUtil;
import com.pj.ca.util.Util;

import javax.crypto.Cipher;
import java.io.ByteArrayOutputStream;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;

/**
 * 描述： rsa非对称操作 实现
 *
 * @author pengjun
 * @date 2021/11/3 11:10
 */
public class RSA implements AsymmetricalCipher, AsymmetricalSignature {

    @Override
    public byte[] encrypt(byte[] data, PublicKey publicKey) throws Exception {
        Cipher cipher = AsymmetricalUtil.getCipherInstance(AsymmetricalCipher.RSA_NOPADDING_CIPHER);
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        int key_len = ((RSAPublicKey) publicKey).getModulus().bitLength() / 8;
        key_len -= 11;
        ByteArrayOutputStream out = new ByteArrayOutputStream(data.length);
        for (int i = 0; i < data.length; i += key_len) {
            byte[] doFinal = cipher.doFinal(Util.subarray(data, i, i + key_len));
            out.write(doFinal, 0, doFinal.length);
        }
        return out.toByteArray();
    }

    @Override
    public byte[] decrypt(byte[] data, PrivateKey privateKey) throws Exception {

        Cipher cipher = AsymmetricalUtil.getCipherInstance(AsymmetricalCipher.RSA_NOPADDING_CIPHER);
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        int key_len = ((RSAPrivateKey) privateKey).getModulus().bitLength() / 8;
        ByteArrayOutputStream out = new ByteArrayOutputStream(data.length);
        for (int i = 0; i < data.length; i += key_len) {
            byte[] doFinal = cipher.doFinal(Util.subarray(data, i, i + key_len));
            out.write(doFinal);
        }
        return out.toByteArray();
    }

    @Override
    public byte[] sign(byte[] data, PrivateKey privateKey, String signAlgorithm) throws Exception {
        Signature signature = AsymmetricalUtil.getSignatureInstance(signAlgorithm);
        signature.initSign(privateKey);
        signature.update(data);
        return signature.sign();
    }

    @Override
    public boolean verifySign(byte[] signData, byte[] content, PublicKey publicKey, String signAlgorithm) throws Exception {
        Signature signature = AsymmetricalUtil.getSignatureInstance(signAlgorithm);
        signature.initVerify(publicKey);
        signature.update(content);
        return signature.verify(signData);
    }
}
